#ifndef __BACKTRACE_H___
#define __BACKTRACE_H___
#ifdef __linux__
#include <execinfo.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#define ERR_DUMP_MAX_LEN 4096

#define mysnprintf(_b, _s, _f, ...) ({char *b=_b; int r=0; if(_s>0){ r=snprintf(b,_s,_f,##__VA_ARGS__); if (r>=_s){r=_s-1;} b[r]=0;} r;})

static inline void dump_backtrace(char *filepath)
{
    char dump_buf[ERR_DUMP_MAX_LEN];
    int dump_len = 0; 
    void *array[100];
    char **strings;
    int i;
    time_t t = time(NULL);
    struct tm tm;
    localtime_r(&t, &tm);
    dump_len += mysnprintf(dump_buf + dump_len, ERR_DUMP_MAX_LEN - dump_len, "**************START**************\n");
    dump_len += mysnprintf(dump_buf + dump_len, ERR_DUMP_MAX_LEN - dump_len, "%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min,tm.tm_sec);
    int size = backtrace(array, 100); 
    strings = backtrace_symbols (array, size);
    dump_len += mysnprintf(dump_buf + dump_len, ERR_DUMP_MAX_LEN - dump_len, "Obtained %d stack frames\n", size);
    for (i = 0; i < size; i++) {
        dump_len += mysnprintf(dump_buf + dump_len, ERR_DUMP_MAX_LEN - dump_len, "%s\n", strings[i]);
    }    
    dump_len += mysnprintf(dump_buf + dump_len, ERR_DUMP_MAX_LEN - dump_len, "************** END **************\n\n");
    printf("%.*s", dump_len, dump_buf);
    int fd;
    if ((fd = open(filepath, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)) >= 0) { 
        if (write(fd, dump_buf, dump_len) <= 0 ) {
            printf("write error[%m]\n");
        }    
        close(fd);
    }    
}

#endif
#endif
